home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 4: GNU Archives / Linux Cubed Series 4 - GNU Archives.iso / gnu / glibc-1.09 / glibc-1 / glibc-1.09.1 / mach / devstream.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-29  |  5.5 KB  |  265 lines

  1. /* stdio on a Mach device port.
  2.    Translates \n to \r\n on output.
  3.  
  4. Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
  5. This file is part of the GNU C Library.
  6.  
  7. The GNU C Library is free software; you can redistribute it and/or
  8. modify it under the terms of the GNU Library General Public License as
  9. published by the Free Software Foundation; either version 2 of the
  10. License, or (at your option) any later version.
  11.  
  12. The GNU C Library is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15. Library General Public License for more details.
  16.  
  17. You should have received a copy of the GNU Library General Public
  18. License along with the GNU C Library; see the file COPYING.LIB.  If
  19. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  20. Cambridge, MA 02139, USA.  */
  21.  
  22. #include <stdio.h>
  23. #include <mach.h>
  24. #include <device/device.h>
  25. #include <errno.h>
  26. #include <string.h>
  27.  
  28. static int
  29. input (FILE *f)
  30. {
  31.   kern_return_t err;
  32.   char *buffer;
  33.   size_t to_read;
  34.   mach_msg_type_size_t nread;
  35.   char c;
  36.  
  37.   if (f->__buffer == NULL)
  38.     {
  39.       buffer = &c;
  40.       to_read = 1;
  41.     }
  42.   else
  43.     {
  44.       buffer = f->__buffer;
  45.       to_read = f->__bufsize;
  46.     }
  47.  
  48.   f->__eof = 0;
  49.  
  50.   nread = to_read;
  51.   err = device_read_inband ((device_t) f->__cookie, 0, f->__target,
  52.                 to_read, buffer, &nread);
  53.  
  54.   if (err)
  55.     {
  56.       f->__error = 1;
  57.       f->__bufp = f->__get_limit = f->__put_limit = f->__buffer;
  58.       errno = err;
  59.       return EOF;
  60.     }
  61.  
  62.   /* Echo it back.  */
  63.   err = device_write_inband ((device_t) f->__cookie, 0, f->__target,
  64.                  buffer, nread, (int *) &to_read);
  65.  
  66.   if (f->__buffer == NULL)
  67.     return (unsigned char) c;
  68.  
  69.   f->__get_limit = f->__buffer + nread;
  70.   f->__bufp = f->__buffer;
  71.   f->__put_limit = f->__buffer + (f->__mode.__write ? f->__bufsize : 0);
  72.   return (unsigned char) *f->__bufp++;
  73. }
  74.  
  75.  
  76. #if 0
  77. static void
  78. output (FILE *f, int c)
  79. {
  80.   inline void write_some (const char *p, size_t to_write)
  81.     {
  82.       kern_return_t err;
  83.       int wrote;
  84.       while (to_write > 0)
  85.     {
  86.       if (err = device_write ((device_t) f->__cookie, 0,
  87.                   f->__target, (char *)p, 
  88.                   to_write, &wrote))
  89.         {
  90.           errno = err;
  91.           f->__error = 1;
  92.           break;
  93.         }
  94.       p += wrote;
  95.       to_write -= wrote;
  96.       f->__target += wrote;
  97.     }
  98.     }
  99.  
  100.   if (f->__buffer != NULL)
  101.     {
  102.       if (f->__put_limit == f->__buffer)
  103.     {
  104.       /* Prime the stream for writing.  */
  105.       f->__put_limit = f->__buffer + f->__bufsize;
  106.       f->__bufp = f->__buffer;
  107.       if (c != EOF)
  108.         {
  109.           *f->__bufp++ = (unsigned char) c;
  110.           c = EOF;
  111.         }
  112.     }
  113.  
  114.  
  115.       /* Write out the buffer.  */
  116.  
  117.       write_some (f->__buffer, f->__bufp - f->__buffer);
  118.  
  119.       f->__bufp = f->__buffer;
  120.     }
  121.  
  122.   if (c != EOF && !ferror (f))
  123.     {
  124.       if (f->__linebuf && (unsigned char) c == '\n')
  125.     {
  126.       static const char nl = '\n';
  127.       write_some (&nl, 1);
  128.     }
  129.       else
  130.     *f->__bufp++ = (unsigned char) c;
  131.     }
  132. }
  133. #endif
  134.  
  135.  
  136. static void
  137. output (FILE *f, int c)
  138. {
  139.   void write_some (const char *p, size_t to_write)
  140.     {
  141.       kern_return_t err;
  142.       int wrote;
  143.       while (to_write > 0)
  144.     {
  145.       if (err = device_write_inband ((device_t) f->__cookie, 0,
  146.                      f->__target, p, to_write, &wrote))
  147.         {
  148.           errno = err;
  149.           f->__error = 1;
  150.           break;
  151.         }
  152.       p += wrote;
  153.       to_write -= wrote;
  154.       f->__target += wrote;
  155.     }
  156.     }
  157.   void write_crlf (void)
  158.     {
  159.       static const char crlf[] = "\r\n";
  160.       write_some (crlf, 2);
  161.     }
  162.  
  163.   if (f->__buffer == NULL)
  164.     {
  165.       /* The stream is unbuffered.  */
  166.  
  167.       if (c == '\n')
  168.     write_crlf ();
  169.       else if (c != EOF)
  170.     {
  171.       char cc = (unsigned char) c;
  172.       write_some (&cc, 1);
  173.     }
  174.  
  175.       return;
  176.     }
  177.  
  178.   if (f->__put_limit == f->__buffer)
  179.     {
  180.       /* Prime the stream for writing.  */
  181.       f->__put_limit = f->__buffer + f->__bufsize;
  182.       f->__bufp = f->__buffer;
  183.       if (c != EOF)
  184.     {
  185.       *f->__bufp++ = (unsigned char) c;
  186.       c = EOF;
  187.     }
  188.     }
  189.  
  190.   {
  191.     /* Search for newlines (LFs) in the buffer.  */
  192.  
  193.     char *start = f->__buffer, *p = start;
  194.  
  195.     while (!ferror (f) && (p = memchr (p, '\n', f->__bufp - start)))
  196.       {
  197.     /* Found one.  Replace it with a CR and write out through that CR.  */
  198.  
  199.     *p = '\r';
  200.     write_some (start, p + 1 - start);
  201.  
  202.     /* Change it back to an LF; the next iteration will write it out
  203.        first thing.  Start the next searching iteration one char later.  */
  204.  
  205.     start = p;
  206.     *p++ = '\n';
  207.       }
  208.  
  209.     /* Write the remainder of the buffer.  */
  210.  
  211.     if (!ferror (f))
  212.       write_some (start, f->__bufp - start);
  213.   }
  214.  
  215.   f->__bufp = f->__buffer;
  216.  
  217.   if (c != EOF && !ferror (f))
  218.     {
  219.       if (f->__linebuf && (unsigned char) c == '\n')
  220.     write_crlf ();
  221.       else
  222.     *f->__bufp++ = (unsigned char) c;
  223.     }
  224. }
  225.  
  226. static int
  227. dealloc_ref (void *cookie)
  228. {
  229.   if (mach_port_deallocate (mach_task_self (), (mach_port_t) cookie))
  230.     {
  231.       errno = EINVAL;
  232.       return -1;
  233.     }
  234.   return 0;
  235. }
  236.  
  237.  
  238. FILE *
  239. mach_open_devstream (mach_port_t dev, const char *mode)
  240. {
  241.   FILE *stream;
  242.  
  243.   if (mach_port_mod_refs (mach_task_self (), dev, MACH_PORT_RIGHT_SEND, 1))
  244.     {
  245.       errno = EINVAL;
  246.       return NULL;
  247.     }
  248.  
  249.   stream = fopencookie ((void *) dev, mode, __default_io_functions);
  250.   if (stream == NULL)
  251.     {
  252.       mach_port_deallocate (mach_task_self (), dev);
  253.       return NULL;
  254.     }
  255.  
  256.   stream->__room_funcs.__input = input;
  257.   stream->__room_funcs.__output = output;
  258.   stream->__io_funcs.__close = dealloc_ref;
  259.   stream->__io_funcs.__seek = NULL; /* Cannot seek.  */
  260.   stream->__io_funcs.__fileno = NULL; /* No corresponding POSIX.1 fd.  */
  261.   stream->__seen = 1;
  262.  
  263.   return stream;
  264. }
  265.